package com.googlecode.monitoring.ws.dao;

import com.googlecode.monitoring.dao.XmlUtils;
import com.googlecode.monitoring.exception.DataDaoException;
import com.googlecode.monitoring.model.Person;
import com.googlecode.monitoring.ws.model.CfpContext;
import com.googlecode.monitoring.ws.model.CfpSecurity;
import com.googlecode.monitoring.ws.model.TestFrameworkConfig;
import com.googlecode.monitoring.ws.model.WsItemToCheck;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class WsAgentXmlUtils {

    XmlUtils xmlUtils;

    @Autowired
    public void setXmlUtils(XmlUtils xmlUtils) {
        this.xmlUtils = xmlUtils;
    }

	protected WsItemToCheck buildInstanceToCheck(Element xmlItemElmnt, Set<Person> alertPersons) {
		Node idNode = xmlItemElmnt.getElementsByTagName("id").item(0);
		Node nameNode = xmlItemElmnt.getElementsByTagName("name").item(0);
		Node descriptionNode = xmlItemElmnt.getElementsByTagName("description").item(0);
		Node eventTimeNode = xmlItemElmnt.getElementsByTagName("eventTime").item(0);
		NodeList personNodeList = xmlItemElmnt.getElementsByTagName("person");
		Element testConfigNode = (Element) xmlItemElmnt.getElementsByTagName("testConfig").item(0);
		Node stateNode = xmlItemElmnt.getElementsByTagName("state").item(0);

		WsItemToCheck wsItem = new WsItemToCheck();
        if(idNode == null || idNode.getTextContent()==null || idNode.getTextContent().isEmpty()){
            throw new DataDaoException("WsItemToCheck must be with unique ID");
        }
        wsItem.setId(idNode.getTextContent());
		wsItem.setName(getNodeTextContent(nameNode));
		wsItem.setDescr(getNodeTextContent(descriptionNode));
		wsItem.setEventTime(xmlUtils.buildEventTime(eventTimeNode));
		wsItem.setResponsiblePersons(xmlUtils.mergePersons(personNodeList, alertPersons));
		wsItem.setTestFrameworkConfig(buildTestConfig(testConfigNode));
		wsItem.setCurrentState(xmlUtils.buildState(stateNode));

		return wsItem;
	}

    private TestFrameworkConfig buildTestConfig(Element xml) {
		if (xml==null) {
			return null;
		}
		
		Node targetUrl = xml.getElementsByTagName("targetUrl").item(0);
		Node namespace = xml.getElementsByTagName("namespace").item(0);
		Node namespacePrefix = xml.getElementsByTagName("namespacePrefix").item(0);
		Node useCaseLocation = xml.getElementsByTagName("useCaseLocation").item(0);
		NodeList useCaseFilters = xml.getElementsByTagName("useCaseFilter");
		Node testCaseLocation = xml.getElementsByTagName("testCaseLocation").item(0);
		Node useHeader = xml.getElementsByTagName("useHeader").item(0);
		Element security = (Element) xml.getElementsByTagName("security").item(0);
		Element cfpContext = (Element) xml.getElementsByTagName("cfpContext").item(0);

		TestFrameworkConfig config = new TestFrameworkConfig();

		config.setTargetUrl(getNodeTextContent(targetUrl));
		config.setNamespace(getNodeTextContent(namespace));
		config.setNamespacePrefix(getNodeTextContent(namespacePrefix));
		config.setUseCaseLocation(getNodeTextContent(useCaseLocation));
		config.setUseCaseFilters(buildUseCaseFilters(useCaseFilters));
		config.setTestCaseLocation(getNodeTextContent(testCaseLocation));

		config.setUseHeader(buildBoolean(useHeader,true));
		if (config.isUseHeader()) {
			config.setCfpSecurity(buildCfpSecurity(security));
			config.setCfpContext(buildCfpContext(cfpContext));
		}

		return config;
	}

	private boolean buildBoolean(Node node, boolean defaultValue) {
		if (node == null) {
			return defaultValue;
		}
		return Boolean.parseBoolean(getNodeTextContent(node));
	}

	private CfpContext buildCfpContext(Element xml) {
		Node modelId = xml.getElementsByTagName("modelId").item(0);
		Node channelId = xml.getElementsByTagName("channelId").item(0);

		CfpContext context = new CfpContext();

		context.setModelId(getNodeTextContent(modelId));
		context.setChannelId(getNodeTextContent(channelId));

		return context;
	}

	private CfpSecurity buildCfpSecurity(Element xml) {
		Node user = xml.getElementsByTagName("user").item(0);
		Node password = xml.getElementsByTagName("password").item(0);

		CfpSecurity security = new CfpSecurity();

		security.setLogin(getNodeTextContent(user));
		security.setPassword(getNodeTextContent(password));

		return security;
	}

	private List<String> buildUseCaseFilters(NodeList nodes) {
		List<String> filters = new ArrayList<String>(nodes.getLength());

		for (int i = 0; i < nodes.getLength(); i++) {
			filters.add(getNodeTextContent(nodes.item(i)));
		}

		return filters;
	}

	protected String getNodeTextContent(Node node) {
		if (node != null) {
			return node.getTextContent().trim();
		}
		return null;
	}
}
